﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.ServiceProcess;
using System.Text;
using System.Xml;
using System.Windows.Forms;

namespace ServiceEx
{
    partial class Service1 : ServiceBase
    {
        string[] exePaths;
        int[] pids = null;
        int num = 0;

        QT.IO.XML xml = new QT.IO.XML(Application.StartupPath + @".\ServiceEx.xml");

        public Service1()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            try
            {
                exePaths = xml.MultiRead(@"/ServiceEx/ExeList/Path", "");
            }
            catch (Exception ex)
            {
                ErrLog(ex.Message);
                return;
            }
            num = exePaths.Length;

            if (num > 0)
            {
                pids = new int[num];
                try
                {
                    for (int i = 0; i < num; i++)
                    {
                        if (!File.Exists(exePaths[i]))
                        {
                            ErrLog(exePaths[i] + "不存在");
                            continue;
                        }
                        RunProcess(exePaths[i], i);
                        ErrLog("程序" + exePaths[i] + "已启动,Pid:" + pids[i]);
                    }
                }
                catch (Exception ex)
                {
                    ErrLog(ex.Message);
                }
            }
            else
            {
                ErrLog("未找到节点\"/ServiceEx/ExeList/Path\"");
            }

            this.timer1.Start();
        }

        protected override void OnStop()
        {
            this.timer1.Stop();
            for (int i = 0; i < num; i++)
            {
                try
                {
                    using (Process pro = Process.GetProcessById(pids[i]))
                    {
                        if (!pro.CloseMainWindow()) pro.Kill();
                        ErrLog("程序" + exePaths[i] + "(Pid:" + pids[i] + ")正常关闭");
                    }
                }
                catch (Exception ex)
                {
                    ErrLog(ex.Message);
                    continue;
                }
            }
        }

        private void RunProcess(string exePath,int index)
        {
            Process process = null;
            try
            {
                process = new Process();
                process.StartInfo.FileName = exePath;
                process.StartInfo.UseShellExecute = true;
                process.Start();
                pids[index] = process.Id;
            }
            catch (Exception ex)
            {
                ErrLog(ex.Message);
            }
            finally
            {
                process.Dispose();
            }
        }

        private void MonitorProcess()
        {
            for (int i = 0; i < pids.Length; i++)
            {
                try
                {
                    using (Process pro = Process.GetProcessById(pids[i]))
                    {
                        if (pro.HasExited)
                        {
                            ErrLog("检测到程序" + exePaths[i] + "(Pid:" + pids[i] + ")意外关闭");
                            RunProcess(exePaths[i], i);
                            ErrLog("已重启程序" + exePaths[i] + ",Pid:" + pids[i]);
                        }
                    }
                }
                catch (ArgumentException)
                {
                    ErrLog("检测到程序" + exePaths[i] + "(Pid:" + pids[i] + ")意外关闭");
                    RunProcess(exePaths[i], i);
                    ErrLog("已重启程序" + exePaths[i] + ",Pid:" + pids[i]);
                }
                catch (Exception ex)
                {
                    ErrLog(ex.Message);
                    continue;
                }
            }
        }

        public void ErrLog(string text)
        {
            FileStream fs = null;
            StreamWriter txt = null;
            try
            {
                string File = xml.Read("/ServiceEx/LogPath", "");
                fs = new FileStream(File, FileMode.Append, FileAccess.Write, FileShare.None);
                txt = new StreamWriter(fs);

                txt.WriteLine("[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] " + text);
            }
            catch (Exception ex)
            {
                string File = @".\err.log";
                FileStream fm = null;
                StreamWriter sw = null;
                try
                {
                    fm = new FileStream(File, FileMode.Append, FileAccess.Write, FileShare.None);
                    sw = new StreamWriter(fm);

                    sw.WriteLine("[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] " + ex.Message);
                }
                finally
                {
                    fm.Dispose();
                }
            }
            finally
            {
                fs.Dispose();
            }
        }

        private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            MonitorProcess();
        }
    }
}
